深度学习算法(第29期)----可视化自编码器和无监督预训练
上期我们一起学习了深度学习中的如何高效的训练自编码器的相关知识,
深度学习算法(第28期)----如何高效的训练自编码器?
今天我们一起学一下自编码器中相关的可视化方面以及无监督预训练方面的知识。
可视化重构
如何确保自编码器训练了一个合适的模型呢?一个常用的方法是比较模型的输入和输出,当输入和输出大体相似,并且不相似的地方也都是一些不重要的细节的时候,那么该模型算了可以了。我们以MNIST中随机挑选的两个数字为例:
其中左边的是原始数据,右边的是重构的数据,代码如下:
n_test_digits = 2
X_test = mnist.test.images[:n_test_digits]
with tf.Session() as sess:
[...] # Train the Autoencoder
outputs_val = outputs.eval(feed_dict={X: X_test})
def plot_image(image, shape=[28, 28]):
plt.imshow(image.reshape(shape), cmap="Greys", interpolation="nearest")
plt.axis("off")
for digit_index in range(n_test_digits):
plt.subplot(n_test_digits, 2, digit_index * 2 + 1)
plot_image(X_test[digit_index])
plt.subplot(n_test_digits, 2, digit_index * 2 + 2)
plot_image(outputs_val[digit_index])
从重构上看,输出已经和输入足够接近。因此,自编码器已经学会了如何生成和自己一样的输出,但是它到底学到了哪些有用的特征呢?
可视化特征
一旦我们自编码器学到了一些特征,我们就会想去看看到底到底有哪些特征。有很多技术可以实现,一般认为最简单的方法就是考虑每一个隐藏层中的每一个神经元,找到激活该神经元最多的训练样本。这在最顶层的隐藏层比较好用,因为它能捕获相对更大更具体一些的特征,然后就可以很容易的找到包含该特征的训练样本。比如,当一个神经元看到一只猫的时候,该神经元经常被激活,那么激活该神经元的大多数图片上应该都包含一只猫。然而对于低级的隐藏层,这种方法不是十分奏效,因为低层次的特征更加小而且更加抽象,因此很难去准确的理解什么到底什么输入激活了这些神经元。
还有一种方法,对于第一个隐藏层中的每个神经元,您可以创建一个图像,其中像素的强度对应于给定神经元的连接权重。例如,以下代码绘制了第一个隐藏层中五个神经元学习的特征:
with tf.Session() as sess:
[...] # train autoencoder
weights1_val = weights1.eval()
for i in range(5):
plt.subplot(1, 5, i + 1)
plot_image(weights1_val.T[I])
这样我们就得到了低层次的一些特征,如下图:
上图中前四个特征似乎对应于一些小块,而第五个特征似乎寻找竖直条纹(需要注意的是,这些特征来自堆叠去噪自编码器,我们将在下期讨论)。
另一项技术是给自编码器随机输入一张图片,来衡量你感兴趣的神经元的激活情况,然后执行反向传播来调整图像,使该神经元激活得更多。迭代几次之后(执行梯度上升),图像将逐渐变成使该神经元激活最多的图像。这是一种有用的技术,常用于可视化神经元比较感兴趣的输入类型。
最后,如果使用自编码器执行无监督预训练(例如,对于分类任务),验证自编码器学习的特征是否有用的一种简单方法是用这些特征来训练分类器,然后看分类器的性能。
无监督预训练
正如我们前面讨论的那样,如果您正在处理复杂的监督任务,但是并没有大量标记的训练数据,那么一种解决方案是找到执行类似任务的神经网络,然后重新使用其较低层。这样就使得仅使用很少的训练数据来训练高性能模型成为可能,因为我们的神经网络不必学习所有的低级特征;它将基于已有的低级特征继续学习。
同样,如果我们有一个大型数据集,但大多数数据集未标记,我们首先可以使用所有数据训练一个栈式自编码器,然后复用该自编码器的较低层,来创建我们实际需要的网络,并使用标记数据对其进行训练。
这项技术还是蛮实用的,因为创建一个大的没标签的数据集很容易,但是人工打标签成本还是比较昂贵的。
正如我们前面所讨论的那样,当前深度学习海啸的触发因素之一是Geoffrey Hinton等人在2006年的发现,深度神经网络可以以无监督的方式进行预训练。TensorFlow 的实现没有什么特别之处:只需使用所有训练数据训练自编码器,然后复用其编码层以创建一个新的神经网络。
到目前为止,为了强制自编码器学习有趣的特性,我们限制了编码层的大小,使其不够完善。实际上可以使用许多其他类型的约束,包括允许编码层与输入一样大或甚至更大的约束,导致过度完成的自编码器。下期我们将继续学习不同类型的自编码器。
好了,至此,今天我们简单学习了可视化自编码器和无监督的自编码器预训练的相关知识,希望有些收获,下期我们将更深一步的学习不同类型的自编码器的相关知识,欢迎留言或进社区共同交流,喜欢的话,就点个“在看”吧,您也可以置顶公众号,第一时间接收最新内容。